import {DagreLayout} from "@antv/layout";
import {useReplaceNode} from "../compositions/useReplaceNode";

function getEdgeConfigByDialogData({cell, edgeCount}) {
  const {x, y} = cell.getPosition()
  const {width, height} = cell.getSize()
  const offsetY = 100 // px
  const offsetX = 100  // px

  let edgeConfigs = []

  for (let i = 0; i < edgeCount; i++) {
    const verticeX = x + width / 2 + offsetX * i - offsetX * (edgeCount - 1) / 2
    const verticeY = y + height + offsetY

    const targetX = verticeX
    const targetY = verticeY + offsetY

    edgeConfigs.push({
      verticeX,
      verticeY,
      targetX,
      targetY,
    })
  }

  return edgeConfigs
}


export const nodeDialogConfirm = {
  start({cell, dialogData}, graph, vm) {
    vm.canvasData = {
      ...dialogData
    }

    cell.setAttrs({
      'label': {
        'text': dialogData.name
      },
    })
  },

  condition({cell, dialogData}, graph) {
    const {name} = dialogData
    cell.setAttrs({
      'label': {
        'text': name
      },
    })
  },

  event({cell, dialogData}, graph) {
    const {name} = dialogData
    cell.setAttrs({
      'label': {
        'text': name
      },
    })
  },

  switcherCondition({cell, dialogData}, graph) {
    const {name} = dialogData
    cell.setAttrs({
      'label': {
        'text': name + '-条件'
      },
    })
  },

  switcherConcurrent({cell, dialogData}, graph) {
    const {name} = dialogData
    cell.setAttrs({
      'label': {
        'text': name + '-并行'
      },
    })
  },

  abtest({cell, dialogData}, graph) {
    const {weights, name} = dialogData

    // ABTEST节点名
    cell.setAttrs({
      'label': {
        'text': name
      }
    })

    // 布局用model
    const abtestNodeModel = {
      shape: 'abtest',
      size: cell.getSize(),
      id: cell.id,
      ports: cell.ports,
      data: cell.getData(),
    }
    // 布局定位初始锚点
    const _dropPosition = cell.getPosition()

    // TODO 需要改进
    // 清除原来的连线
    // const currentOutEdges = graph.getOutgoingEdges(cell) || []
    // currentOutEdges.forEach(edge => {
    //   graph.removeEdge(edge)
    // })
    const currentOutEdges = graph.getOutgoingEdges(cell) || []

    // 布局用model
    // let nodeModels = []
    // let edgeModels = []

    for (let i = 0; i < weights.length; i++) {
      const weight = weights[i]
      const edgeCell = currentOutEdges.find(edgeCell => edgeCell.getData().dialogData.id === weight.id)
      const edgeLabel = `实验组${i + 1}: ${weight.weighted}%`

      if (edgeCell) { // 已存在的实验组 => 更新 //更新当前edge的data 和 对应的targetNode中的数据
        console.log('更新实验组', edgeLabel)
        edgeCell.setLabels(edgeLabel)
        edgeCell.setData({
          dialogData: {
            ...weight
          }
        })
      } else { // 不存在的实验组 => 新增 // 创建placeholder 在placeholder保存当前weight的信息
        console.log('新增实验组', edgeLabel)
        // 创建新增实验组的占位节点与边， 关联新增占位节点与新增边
        const placeholderNode = graph.addNode({
          shape: 'placeholder',
          data: {
            abtestWeightInfo: {...weight}
          }
        })
        graph.addEdge({
          shape: 'abtest-edge',
          source: {
            cell: cell.id,
            port: cell.getPortsByGroup('bottom')[0].id
          },
          target: {
            cell: placeholderNode.id,
            port: placeholderNode.getPortsByGroup('top')[0].id
          },
          label: edgeLabel,
          data: {
            dialogData: {
              ...weight
            }
          }
        })
      }
    }
    // 未在实验组列表中出现的边节点 => 删除
    for (let i = 0; i < currentOutEdges.length; i++) {
      const edgeCell = currentOutEdges[i]
      const targetWeight = weights.find(weight => weight.id === edgeCell.getData().dialogData.id)
      // 未在实验组列表中匹配到上次的边，视为已删除，删除这条边连接，若终点为placeholder一并删除
      if (!targetWeight) {
        console.log('删除了ABTEST的一条边', edgeCell)
        const edgeCellTargetNode = edgeCell.getTargetNode()
        if (edgeCellTargetNode.shape === 'placeholder') {
          graph.removeCell(edgeCellTargetNode)
        }

        graph.removeCell(edgeCell.id)
      }
    }

    // 布局
    const dagreLayout = new DagreLayout({
      type: 'dagre',
      rankdir: 'TB',
      nodesep: 30,
      ranksep: 40,
    }).layout({
      nodes: [
        {
          id: cell.id,
          size: cell.getSize(),
        },
        ...graph.getNeighbors(cell, {outgoing: true}).map((outgoingCell => ({
          id: outgoingCell.id,
          size: outgoingCell.getSize()
        })))
      ],
      edges: [
        ...(graph.getOutgoingEdges(cell) ?? []).map(edgeCell => ({
          source: edgeCell.getSourceCellId(),
          target: edgeCell.getTargetCellId(),
          source_add: {
            cell: cell.id,
            port: cell.getPortsByGroup('bottom')[0].id
          },
          target_add: {
            cell: edgeCell.getTargetCellId(),
            port: edgeCell.getTargetCell().getPortsByGroup('top')[0].id
          },
          shape: 'abtest-edge',
          label: edgeCell.getLabels()[0] || '',
          data: {
            ...edgeCell.getData()
          }
        }))
      ],
    })
    console.log('abtest 布局重排', dagreLayout)
    // 应用布局计算后的坐标
    const positionedAbtestNode = dagreLayout.nodes.find(item => item.id === cell.id)
    const offsetX = _dropPosition.x - positionedAbtestNode.x
    const offsetY = _dropPosition.y - positionedAbtestNode.y
    dagreLayout.nodes.forEach((node) => {
      const targetCell = graph.getCellById(node.id)
      targetCell.position(node.x + offsetX, node.y + offsetY, {deep: true})
    })

    // 刷新边，仅改变node的position没有使边的路由重绘，会导致路由变形，并且没有API能够触发边的重绘
    // 重新创建边 使其重绘
    const oldEdgeCells = graph.getOutgoingEdges(cell) ?? []
    oldEdgeCells.forEach((edgeCell) => {
      graph.removeCell(edgeCell)
    })
    dagreLayout.edges.forEach(edge => {
      const edgeModel = {
        ...edge,
        source: {...edge.source_add},
        target: {...edge.target_add},
      }
      delete edge.source_add
      delete edge.target_add
      graph.addEdge(edgeModel)
    })
  },

  wait({cell, dialogData}, graph) {
    const {name} = dialogData

    cell.setAttrs({
      'label': {
        'text': name
      }
    })
  },

  workWechat({cell, dialogData}, graph) {
    const {name} = dialogData

    cell.setAttrs({
      'label': {
        'text': name
      }
    })
  },

  publicNumber({cell, dialogData}, graph) {
    const {name} = dialogData

    cell.setAttrs({
      'label': {
        'text': name
      }
    })
  },

}

/**
 * 连接桩的显示与隐藏事件
 */
export const portVisibleSwitch = {
  showPorts(ports, show) {
    for (let i = 0, len = ports.length; i < len; i = i + 1) {
      ports[i].style.visibility = show ? 'visible' : 'hidden'
    }
  },

  mouseenter(e, graph) {
    // 连接桩显示
    const container = document.getElementById('graph-container')
    const ports = container.querySelectorAll(
      '.x6-port-body',
    )
    this.showPorts(ports, true)
  },

  mouseleave(e, graph) {
    const container = document.getElementById('graph-container')
    const ports = container.querySelectorAll(
      '.x6-port-body',
    )
    this.showPorts(ports, false)
  },

  blankClick(e, graph) {
    this.mouseleave(e, graph)
  },

  cellselected(e, graph) {
    this.mouseleave(e, graph)
  }
}

/**
 * 删除按钮的显示与隐藏
 */
export const deleteButtonVisibleSwitch = {
  mouseenter(e) {
    if (e.cell.shape === 'start') {
      return
    }

    e.node.addTools({
      name: 'delete-item',
    })
  },

  mouseleave(e) {
    // 删除按钮隐藏
    e.node.removeTools()
  },

  blankClick(e, graph) {
    const cells = graph.getCells()
    cells.forEach(item => {
      item.removeTools()
    })
  },

  cellselected(e, graph) {
    e.cell.removeTools()
  }
}

/**
 * 占位节点的检测与替换
 */
export const PlaceholderReplace = {
  zIndex: 1,
  nodemousedown(e, graph) {
    this.zIndex = e.node.getZIndex()
    e.node.toFront()
  },

  nodemouseup(e, graph) {
    // 还原
    // BUG: 此时还原zIndex 会导致下一次dblclick 触发失败
    // e.node.setZIndex(this.zIndex)
    // 已有连线关系的节点不做替换
    const outgoingEdges = graph.getOutgoingEdges(e.node) || []
    const incomingEdges = graph.getIncomingEdges(e.node) || []
    if (outgoingEdges.length || incomingEdges.length) {
      return
    }
    const nodesUnderNode = graph.getNodesUnderNode(e.node, {by: 'center'}) || []
    if (!nodesUnderNode.length) {
      return
    }
    const placeholderNodes = nodesUnderNode.filter(item => item.shape === 'placeholder')
    if (!placeholderNodes.length) {
      return
    }

    useReplaceNode({
      placeholderNode: placeholderNodes[placeholderNodes.length - 1], // graph上已存在的占位节点
      transferNode: e.node, // 当前鼠标事件中操作的节点
      graph,
    })
  },
}
